package com.youbo.cloudmall.search.service.impl;

import com.youbo.cloudmall.search.config.CloudMallElasticSearchConfig;
import com.youbo.cloudmall.search.service.MallSearchService;
import com.youbo.cloudmall.search.vo.SearchParam;
import com.youbo.cloudmall.search.vo.SearchResult;
import com.youbo.common.constant.EsConstant;
import org.apache.commons.lang3.StringUtils;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.NestedQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;

/**
 * @author youbo
 * @version 1.0
 * @date 2021/10/14 11:30
 */
@Service
public class MallSearchServiceImpl implements MallSearchService {


    @Autowired
    private RestHighLevelClient client;

    @Override
    public SearchResult search(SearchParam searchParam) {
        //
        SearchResult searchResult = null;
        SearchRequest searchRequest = buildSearchRequest(searchParam);
        try {
            SearchResponse response = client.search(searchRequest, CloudMallElasticSearchConfig.COMMON_OPTIONS);
            searchResult = buildSearchResult(response);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return searchResult;
    }

    /**
     * 构建结果数据
     * @param response
     * @return com.youbo.cloudmall.search.vo.SearchResult
     */

    private SearchResult buildSearchResult(SearchResponse response) {
        return null;
    }

    /**
     * 准备检索请求
     * 模糊匹配，过滤（属性、分类、品牌、价格区间、库存），排序，分页，高亮，聚合分析
     * @param
     * @return org.elasticsearch.action.search.SearchRequest
     */

    private SearchRequest buildSearchRequest(SearchParam param) {
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();//用来构建DSL语句

        //查询：糊匹配，过滤（属性、分类、品牌、价格区间、库存）
        BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();//构建布尔query
        if (!StringUtils.isEmpty(param.getKeyword())){
            boolBuilder.must(QueryBuilders.matchQuery("sku_title",param.getKeyword()));
        }
        //按照三级分类ID查询
        if (param.getCatalog3Id() != null){
            boolBuilder.filter(QueryBuilders.termQuery("catalog_id",param.getCatalog3Id()));
        }

        //品牌id
        if (param.getBrandId() != null && param.getBrandId().size() > 0) {
            boolBuilder.filter(QueryBuilders.termsQuery("brand_id",param.getBrandId()));
        }
        //属性  attrs=1_5寸:8寸
        if (param.getAttrs() != null && param.getAttrs().size() > 0) {

            for (String attr : param.getAttrs()) {
                BoolQueryBuilder nestedBoolQuery = QueryBuilders.boolQuery();
                String[] s = attr.split("_");
                String attrId = s[0];//检索的属性id
                String[] attrValues = s[1].split(":");//检索值
                nestedBoolQuery.must(QueryBuilders.termQuery("attrs.attrId",attrId));
                nestedBoolQuery.must(QueryBuilders.termQuery("attrs.attrValue",attrValues));
                //每个都得生成一个nested查询
                NestedQueryBuilder nestedQuery = QueryBuilders.nestedQuery("attrs", nestedBoolQuery, ScoreMode.None);
                boolBuilder.filter(nestedQuery);

            }

        }

        //库存
        if (param.getHasStock() == 1) {
            boolBuilder.filter(QueryBuilders.termQuery("hasStock",param.getHasStock() == 1));
        }
        //价格区间   skuPrice=1_500  / _500  /500_
        if (!StringUtils.isEmpty(param.getSkuPrice())){
            RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("skuPrice");
            String[] s = param.getSkuPrice().split("_");
            if (s.length == 2) rangeQuery.gte(s[0]).lte(s[1]);
            else if (s.length == 1) {
                if (param.getSkuPrice().startsWith("_")) rangeQuery.gte(s[0]);
                if (param.getSkuPrice().endsWith("_")) rangeQuery.lte(s[0]);
            }
            boolBuilder.filter(rangeQuery);
        }


        sourceBuilder.query(boolBuilder);


        SearchRequest searchRequest = new SearchRequest(new String[]{EsConstant.PRODUCT_INDEX}, sourceBuilder);
        return searchRequest;
    }
}
